/* Copyright (C) 2014-2016 Dan Chapman <dpniel@ubuntu.com>

   This file is part of the dekko

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MSGCOMPOSER_H
#define MSGCOMPOSER_H

#include <QObject>
#include <QPointer>
#include <QQuickTextDocument>
#include "app/Accounts/AccountsManager.h"
#include "app/Accounts/MultipleAccountSenderIdentityModel.h"
#include "app/Models/MessageModel.h"
#include "app/Models/AttachmentListModel.h"
#include "ReplyMode.h"
#include "SubmissionManager.h"
#include "Recipients.h"
#include "app/Settings/MailboxSettings.h"

namespace Dekko
{
class MsgComposer : public QObject
{
    Q_OBJECT
    // Use on mboxsettings to show settings for selected identity and not just currentaccount
    Q_PROPERTY(QObject *selectedAccount READ selectedAccount NOTIFY identityChanged)
    Q_PROPERTY(QObject *identities READ identities NOTIFY modelsChanged)
    Q_PROPERTY(QObject *recipients READ recipients NOTIFY modelsChanged)
    Q_PROPERTY(QObject *manager READ manager WRITE setManager NOTIFY managerChanged)
    Q_PROPERTY(QObject *attachments READ attachments NOTIFY modelsChanged)
    Q_PROPERTY(QObject *mailboxSettings READ mailboxSettings NOTIFY identityChanged)
    // If not replying to a message part just changing the replyMode will update the composer
    // to the correct state i.e building/clearing recipients, reply quoting etc.
    Q_PROPERTY(int replyMode READ replyMode WRITE setReplyMode NOTIFY replyModeChanged)
    Q_PROPERTY(QString subject READ subject WRITE setSubject NOTIFY subjectChanged)
    // This is used when we are replying to a subtree part of a mime message. i.e replying to a forwarded message attachment
    // We create a MessageModel instance of the attachment and treat it just like a normal mime message
    // NOTE: When no replyPart is set the composer defaults to using the currently selected message of the current account
    Q_PROPERTY(QModelIndex replyPart READ replyPart WRITE setReplyPart NOTIFY replyPartChanged)
    Q_PROPERTY(QString mailToUrl READ mailToUrl WRITE setMailToUrl NOTIFY mailToUrlChanged)
    Q_PROPERTY(QQuickTextDocument *body READ body WRITE setBody NOTIFY bodyChanged)
    Q_PROPERTY(QObject *addressbook READ addressbook WRITE setAddressBook NOTIFY addressbookChanged)
    Q_PROPERTY(QObject *submission READ submission NOTIFY modelsChanged)
    Q_PROPERTY(bool isOpened MEMBER m_composerOpen)
    Q_PROPERTY(bool fetchingPart READ isFetchingPart NOTIFY fetchingPartChanged)
    Q_PROPERTY(Errors error READ error NOTIFY hasError)
    Q_PROPERTY(QString errorString READ errorString NOTIFY hasError)

    Q_ENUMS(Errors)

public:
    explicit MsgComposer(QObject *parent = 0);

    enum Errors {
        NO_ERROR,
        NO_VALID_TO_RECIPIENTS,
        NO_VALID_SUBJECT,
        NO_IDENTITIES,
        NO_IDENTITY_SELECTED,
    };

    QObject *selectedAccount() const;
    QObject *identities() const;
    QObject *recipients() const;
    QObject *attachments() const;
    QObject *manager() const;
    void setManager(QObject *manager);

    QObject *mailboxSettings() const;

    QQuickTextDocument *body() const;
    void setBody(QQuickTextDocument *body);

    int replyMode() const;
    void setReplyMode(const int &mode);

    QString subject() const;
    void setSubject(const QString &subject);

    QString mailToUrl() const;
    void setMailToUrl(const QString &url);

    QModelIndex replyPart() const;
    void setReplyPart(const QModelIndex &part);

    QObject *addressbook() const;

    QObject *submission() const;

    bool isFetchingPart() const;

    Errors error() const;
    QString errorString() const;

signals:
    void managerChanged();
    void modelsChanged();
    void replyModeChanged();
    void subjectChanged();
    void replyPartChanged();
    void mailToUrlChanged();
    void bodyChanged();
    void identityChanged();
    void fetchingPartChanged();
    void addressbookChanged(QObject *addressbook);
    void hasError();
    void submissionStarting();

public slots:
    void reset();
    void prepareReply();
    void send();
    void saveDraft(const QString &path);
    void loadDraft(const QString &path);

    void setAddressBook(QObject *addressbook);
    void updateSignatureBlock();
    void appendTextToBody(const QString &text);

private slots:
    void updateComposerSettings();
    void updateIdentityIndex();
    void updateIdentityModel();
//    void fetchPartIndex(const QModelIndex &index);
//    void handlePartReceived(const QString &message);
    void setMessageBody();
    void setError(const Errors &error);

private:
    void parseMailToUrl();
    Accounts::Account *currentAccount();
    QString quoteReplyMessage(const QString &message);
    void resetAutoSaveLocation();

    Accounts::MultipleAccountSenderIdentityModel *m_identities;
    Recipients *m_recipients;
    Accounts::AccountsManager *m_manager;
    Dekko::ReplyMode *m_replyMode;
    Models::MessageModel *m_replyMessage;
    Models::AttachmentListModel *m_attachments;
    QPointer<QQuickTextDocument> m_body;
    Settings::MailboxSettings *m_mboxSettings;
    SubmissionManager *m_submission;
    QString m_subject;
    QString m_mailToUrl;
    QModelIndex m_replyPart;
    QString m_replyPosition;
    bool m_quoteOriginal;
    QList<QByteArray> m_references;
    QByteArray m_inReplyTo;
    QObject *m_addressbook;
    QString m_inProgressDraft;
    bool m_composerOpen;
    bool m_fetchingPart;
    Errors m_error;
    QString m_errorString;
};

}
#endif // MSGCOMPOSER_H
